package com.systec.smalltools.service.impl;

import cn.hutool.core.date.DateUtil;
import com.alibaba.excel.EasyExcel;
import com.systec.smalltools.entity.ExportInfo;
import com.systec.smalltools.entity.ImportInfo;
import com.systec.smalltools.listener.ExcelListener;
import com.systec.smalltools.service.EasyService;
import com.systec.smalltools.util.FileUtils;
import com.systec.smalltools.util.SortUtils;
import com.systec.smalltools.vo.ReadResultVO;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;

import java.io.*;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author cmd
 */
@Service
public class EasyServiceImpl implements EasyService {
    /**
     * //   根据前台传过来的MultipartFile 文件进行解析，将每一条的excel的数据转成ImportInfo
     */
    @Override
    public ReadResultVO getAllImportInfos(MultipartFile file, boolean skipFirstLine) throws Exception {
        String fileName = file.getOriginalFilename();
        //根据文件全路径名，通过字符串的substring的方法，获得文件名字
        String fileSeparator = "\\";
        if (fileName.indexOf(fileSeparator) != -1) {
            fileName = fileName.substring(fileName.lastIndexOf("fileSeparator"));
        }
//      将MultipartFile转化为File
        File toFile;
        if ("".equals(file) || file.getSize() <= 0) {
            toFile = null;
        } else {
            InputStream ins = file.getInputStream();
            toFile = new File(file.getOriginalFilename());
            FileUtils.inputStreamToFile(ins, toFile);
            ins.close();
        }

        //执行easyExcel的切面方法，进行一个excel文件中的记录的获取
        ReadResultVO readResultVO = new ReadResultVO();


        ImportInfo head = null;

        ExcelListener excelListener = new ExcelListener();
        EasyExcel.read(toFile, ImportInfo.class, excelListener).sheet().doRead();

        readResultVO.setImportInfoList(excelListener.importInfoList);
        readResultVO.setProblemLines(excelListener.exceptions);

        //        获取表头
        if (skipFirstLine == false) {
            try {
                head = new ImportInfo(DateUtil.parseDateTime(excelListener.headLine.get(0)), DateUtil.parseDateTime(excelListener.headLine.get(1)));
                System.out.println(head);
                if (head != null && head.getStartTime().after(head.getEndTime())) {
                    readResultVO.getProblemLines().put("0", "时间先后异常！");
                } else {
                    readResultVO.getImportInfoList().add(head);
                }

            } catch (Exception e) {
                e.printStackTrace();
                readResultVO.getProblemLines().put("0", "首行数据不符合格式要求！");
            }

        }
        //删除文件
        toFile.delete();

        SortUtils.listSort(readResultVO.getImportInfoList());


        //        对获取的List<ImportInfo>进行一个排序
        if (excelListener.importInfoList.isEmpty()) {
            readResultVO.setImportInfoList(null);
        }
        return readResultVO;

    }

    /**
     * @param list 获取的每一条excel数据
     * @return 根据获取的全部的importInfo记录，将记录根据startTime的Date分到每一天
     */
    @Override
    public List<List<ImportInfo>> getEveryDayImportInfo(List<ImportInfo> list) {
        //先定义返回的数据
        List<List<ImportInfo>> result = new ArrayList<>();
        //按照日期进行每一天的分离
        String date = null;

        //如果从excel中获取的正确数据为0，直接返回null
        if (list == null || list.isEmpty()) {
            return null;

        } else {
            date = new SimpleDateFormat("yyyy-MM-dd").format(list.get(0).getStartTime());
        }
        //相同的Date的importInfo会放在同一个listDate
        List<ImportInfo> listDate = new ArrayList<>();
        listDate.add(list.get(0));
        for (int i = 1; i < list.size(); i++) {

            String date2 = new SimpleDateFormat("yyyy-MM-dd").format(list.get(i).getStartTime());
            if (date.equals(date2)) {
                listDate.add(list.get(i));
            } else {
                result.add(listDate);
                listDate = new ArrayList<>();
                listDate.add(list.get(i));
                date = date2;
            }

        }
        result.add(listDate);
        return result;
    }


    /**
     * 旧的算法，，通过统计有序的list<importInfo>，通过滑动窗口获得最大的并发量，其中参数intervalTime控制窗口的大小
     *
     * @param intervalTime 并发间隔时间，以分钟为单位
     * @param list         每一天的全部数据
     * @return
     */
    @Override
    public List<ExportInfo> getExportInfos(Integer intervalTime, List<List<ImportInfo>> list) {
        //每一天的list数据为0的时候，直接返回null
        if (list == null || list.isEmpty()) {
            return null;
        }

        //不为空的时候，返回一个List<ExportInfo>的列表，每一个节点表示当天最大的窗口
        List<ExportInfo> result = new ArrayList<>();
        ExportInfo exportInfo = null;
        for (int i = 0; i < list.size(); i++) {
            exportInfo = new ExportInfo();
            if (list.get(i) != null && list.get(i).get(0) != null) {
                //将某一天的date字段写入export中
                exportInfo.setDate(DateUtil.format(list.get(i).get(0).getStartTime(), "YYYY-MM-dd"));

                //使用hutools的dateUtils工具类或者某一天的00：00：00
                Date startOfDate = DateUtil.beginOfDay(list.get(i).get(0).getStartTime());

                //使用hutools的dateUtils工具类或者某一天的23:59:59
                Date endOfDate = DateUtil.endOfDay(list.get(i).get(0).getStartTime());


                //            并发时间段
                //并发窗口左侧开始时间=00：00：00
                Date concurrenceWindowLeft = startOfDate;
                //并发窗口右侧时间=00：00：00左侧窗口+窗口的大小intervalTime（分钟）*60s*1000ms
                Date concurrenceWindowRight = new Date(concurrenceWindowLeft.getTime() + intervalTime * 60 * 1000);

                //改天最大目前最大的并发数量
                int maxConcurrentQuantity = 0;
                //目前最大并发数量之下的窗口--某段时间
                String maxTimeQuantum = null;
                //窗口滑动最多到23：59：59
                while (!concurrenceWindowRight.after(endOfDate)) {
                    int concurrentQuantity = 0;
                    for (int j = 0; j < list.get(i).size(); j++) {
                        if (list.get(i).get(j).getStartTime().before(concurrenceWindowRight) && list.get(i).get(j).getEndTime().after(concurrenceWindowLeft)) {
                            concurrentQuantity++;
                        }

                    }
                    if (concurrentQuantity >= maxConcurrentQuantity) {
                        maxConcurrentQuantity = concurrentQuantity;
                        maxTimeQuantum = DateUtil.format(concurrenceWindowLeft, "HH:mm:ss") + "-" + DateUtil.format(concurrenceWindowRight, "HH:mm:ss");
                    }
                    concurrenceWindowLeft = new Date(concurrenceWindowLeft.getTime() + 60 * 1000);
                    concurrenceWindowRight = new Date(concurrenceWindowLeft.getTime() + intervalTime * 60 * 1000);
                }
                exportInfo.setConcurrentQuantity(maxConcurrentQuantity);
                exportInfo.setTimeQuantum(maxTimeQuantum);
                result.add(exportInfo);
            } else {
                i++;
            }
        }
        return result;
    }


}
